Skip to content

在 ASP.NET 中設定 SameSite Cookies

TLDR

  • SameSite 屬性用於限制第三方 Cookie 的發送,以防禦 CSRF 攻擊。
  • SameSite 共有三個值:None(所有請求發送)、Lax(預設值,僅第一方或連結請求發送)、Strict(僅第一方請求發送)。
  • 在 ASP.NET Core 中,建議透過 CookiePolicyOptions 進行全域設定,並針對舊版瀏覽器實作 User-Agent 檢測以處理 None 值的相容性。
  • 在 ASP.NET Framework 4.7.2+ 中,可透過 Web.confighttpCookies 節點設定全域預設值。
  • ASP.NET_SessionId 的 SameSite 行為受 <sessionState> 設定影響,需特別注意。
  • 瀏覽器對 SameSite 的實作存在差異,開發時應考慮相容性與測試環境(如使用無痕模式)。

SameSite Cookies 核心概念

SameSite 是 IETF 訂立的標準,旨在限制第三方 Cookie 的傳輸,從而降低跨網站要求偽造 (CSRF) 的風險。

Same-Site 屬性值說明

說明
NoneCookie 將在所有請求中發送,現今必須搭配 Secure 屬性。
Lax現今瀏覽器的預設值,僅在第一方上下文或用戶透過連結導向時發送。
StrictCookie 僅會在第一方上下文的請求中發送。

什麼情況下會遇到問題?

當應用程式依賴第三方 Cookie(如跨網域的 iframe 嵌入或 AJAX 請求)時,若設定為 LaxStrict,會導致 Cookie 無法被正確讀取,造成使用者登入狀態失效或功能異常。

WARNING

瀏覽器對 SameSite 的實作並非完全一致。早期版本對未設定 SameSite 的處理方式不盡相同,且 None 值在舊版瀏覽器中可能不被支援,需透過 User-Agent 偵測進行降級處理。


在 ASP.NET Core 設定 SameSite Cookies

全域設定方式

透過 Program.cs 中的 CookiePolicyOptions 進行全域控管,並確保 app.UseCookiePolicy() 放置在 app.UseAuthorization() 之前。

csharp
var builder = WebApplication.CreateBuilder(args);

builder.Services.Configure<CookiePolicyOptions>(options => {
    // 設定最低層級限制
    options.MinimumSameSitePolicy = SameSiteMode.Unspecified;

    // 處理舊版瀏覽器相容性
    options.OnAppendCookie = cookieContext =>
        CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
    options.OnDeleteCookie = cookieContext =>
        CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
});

void CheckSameSite(HttpContext httpContext, CookieOptions options) {
    if (options.SameSite == SameSiteMode.None) {
        var userAgent = httpContext.Request.Headers["User-Agent"].ToString();
        if (DisallowsSameSiteNone(userAgent)) {
            options.SameSite = SameSiteMode.Unspecified;
        }
    }
}

若需針對特定 Cookie 進行設定,可直接在 CookieOptions 中指定:

csharp
Response.Cookies.Append("name", "value", new CookieOptions() { 
    SameSite = SameSiteMode.Lax 
});

在 ASP.NET Framework 設定 SameSite Cookies

此功能需在 Framework 4.7.2 以上版本使用。

Web.config 全域設定

若個別 Cookie 未指定 SameSite,系統將採用 httpCookies 的預設值。

xml
<configuration>
  <system.web>
    <httpCookies sameSite="Lax"></httpCookies>
  </system.web>
</configuration>

舊瀏覽器相容性處理

Global.asax.cs 中攔截請求並過濾不支援 None 的瀏覽器:

csharp
protected void Application_BeginRequest(object sender, EventArgs e) {
    HttpApplication application = sender as HttpApplication;
    var userAgent = application.Context.Request.UserAgent;
    
    if (DisallowsSameSiteNone(userAgent)) {
        HttpContext.Current.Response.AddOnSendingHeaders(context => {
            var cookies = context.Response.Cookies;
            for (var i = 0; i < cookies.Count; i++) {
                if (cookies[i].SameSite == SameSiteMode.None) {
                    cookies[i].SameSite = (SameSiteMode)(-1); // 設為 Unspecified
                }
            }
        });
    }
}

TIP

ASP.NET_SessionId 的 SameSite 設定通常由 <sessionState cookieSameSite="..." /> 控制,而非 httpCookies。測試時建議使用無痕模式,以避免既有 Cookie 影響測試結果。


異動歷程

    • 初版文件建立。